package study.datastructure.leetcode.javase.primary.mutithreads;/**
 * @program: datastructure
 * @author: lcy
 * @create: 2024-09-12 19:27
 */

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 2024/9/12,
 */


public class ReadAndWriteLock {
        private static int number = 0;
        private static final ReadWriteLock lock = new ReentrantReadWriteLock();
        private static final Lock readLock = lock.readLock();
        private static final Lock writeLock = lock.writeLock();
        private static final Condition condition = writeLock.newCondition();
        // 标志是否写入完成
        private static boolean writeComplete = false;

        private static void read() {
            readLock.lock();
            // 如果还没有写入完成，循环等待直到写入完成
            if (!writeComplete) {
                readLock.unlock();
                writeLock.lock();
                while (!writeComplete) {
                    // 等待，并且不要阻塞写入
                    try {
                        condition.await();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                writeLock.unlock();
                readLock.lock();
            }
            System.out.println("number = " + number);
            readLock.unlock();
        }

        private static void write(int change) {
            writeLock.lock();
            number += change;
            System.out.println("写入 " + number);
            writeLock.unlock();
        }

        public static void main(String[] args) throws InterruptedException {
            for (int j = 0; j < 100; j++) {
                number = 0;
                // 开启一个线程写入 100 次 number
                new Thread(() -> {
                    writeComplete = false;
                    for (int i = 0; i < 100; i++) {
                        write(1);
                    }
                    writeComplete = true;
                    // 写入完成，唤醒读取线程，await/signal 操作必须在 lock 时执行。
                    writeLock.lock();
                    condition.signal();
                    writeLock.unlock();
                }).start();

                // 开启一个线程读取 100 次 number
                new Thread(() -> {
                    for (int i = 0; i < 100; i++) {
                        read();
                    }
                }).start();

                // 睡眠一秒保证线程执行完成
                Thread.sleep(1000);
            }
        }
}
